iT邦幫忙

2022 iThome 鐵人賽

DAY 12
0

前情提要

「好,今天來學怎麼模擬!」艾草道。

「模擬什麼?」

「你看你隔壁!」

「ㄟˊ~~這是什麼?另外一個你??不是吧那個月份已經過了呀?」我轉頭看到另一隻艾草。

「嘿嘿嘿!另外一隻我,只有壞小孩才看得到呢!」

「我才不會受到欺騙,快告訴我他是誰?」

「呵呵呵,想知道嗎?就讓我們繼續看下去 …. 」
https://ithelp.ithome.com.tw/upload/images/20220927/20139066cqpLAdQ6yD.png


Mock

今天來介紹 Jest 提供的好用方法 Mock 並練習透過 jest.fn() 來模擬函式,當在撰寫測試,希望專注在撰寫的測試本身(SUT),而不關注該測試的其他依賴函式或套件(DOC)時,就可以透過 Mock 來幫忙實現!

首先來看一下範例程式碼,我們有兩個函式,其中 checkRareMagicAttributes 函式幫我們確認是否為稀有魔法屬性,而 calculateRareAttributesTotal 函式幫忙計算總人數,當在執行 calculateRareAttributesTotal 函式時是會透過傳入的 checkRareMagicAttributes 函式來幫我們確認稀有屬性的人數:

const quizList = [
  {
    name: "艾草",
    attributes: "木"
  },
  {
    name: "Vivian",
    attributes: "火"
  },
  {
    name: "啾啾",
    attributes: "光"
  }
];
// 確認是否為稀有魔法屬性
function checkRareMagicAttributes(attributes) {
  if (attributes === "光" || attributes === "暗") {
    return true;
  } else {
    return false;
  }
}
// 確認屬性稀有屬性人數
function calculateRareAttributesTotal(data) {
  let total = 0;
  data.forEach((item) => {
    if (checkRareMagicAttributes(item.attributes)) {
      total += 1;
    }
  });
  return total;
}

當針對 calculateRareAttributesTotal 撰寫測試而不希望實際去執行 checkRareMagicAttributes 函式時,可以透過 mock 來幫忙實現:

  1. 首先透過 jest.fn() 來模擬一個函式:

    test('Introducing mocks', () => {
    	// arrange
    	// 模擬
    	const mockFunction = jest.fn();
      checkRareMagicAttributes = mockFunction;
    });
    
  2. 接著透過 Jest 提供的方法來設定回傳值:

    1. mockFn.mockReturnValue(value) :mock 每次的回傳值
    2. mockFn.mockReturnValueOnce(value) :mock 一次回傳值,當沒有設定 mockReturnValueOnce 後會回傳 mockReturnValue 設定的回傳值
    test("Introducing mocks", () => {
    	// arrange
      const mockFunction = jest.fn();
      checkRareMagicAttributes = mockFunction;
      // 設定回傳值
      mockFunction.mockReturnValue(false).mockReturnValueOnce(true);
    });
    
  3. 斷言結果:可以透過 calculateRareAttributesTotal 回傳值及 toHaveBeenCalled 來判斷是否有成功呼叫 mockFunction 來斷言。

    test("Introducing mocks", () => {
      // arrange
      const mockFunction = jest.fn();
      checkRareMagicAttributes = mockFunction;
      mockFunction.mockReturnValue(false).mockReturnValueOnce(true);
    
    	// act
      const result = calculateRareAttributesTotal(quizList);
    
    	// assert
      expect(calculateRareAttributesTotal(quizList)).toBe(1);
      expect(mockFunction).toHaveBeenCalled();
    });
    

像這樣就透過 jest.fn() 的方式成功模擬一個函式!

模擬函式回傳的其他方法

jest.fn() 除了可以透過 mockReturnValue 來模擬回傳值外,還有 mockImplementation 方法,可以直接傳入一個模擬函式。

// 範例程式碼取自官方文件
const mockFn = jest.fn(scalar => 42 + scalar);

mockFn(0); // 42
mockFn(1); // 43

mockFn.mockImplementation(scalar => 36 + scalar);

mockFn(2); // 38
mockFn(3); // 39

透過 Jest.fn() 可以更方便模擬依賴函式或套件!

明天來學習透過 spyOn 改寫!


參考文章

https://jestjs.io/zh-Hans/docs/mock-functions
https://jestjs.io/docs/mock-function-api
https://medium.com/enjoy-life-enjoy-coding/jest-jojo是你-我的替身能力是-mock-4de73596ea6e
https://blog.jimmydc.com/mock-asynchronous-functions-with-jest/
https://vhudyma-blog.eu/3-ways-to-mock-axios-in-jest/
https://www.youtube.com/watch?v=1Xafx6o82Aw&ab_channel=SoftwareTestingHelp
https://dwatow.github.io/2020/04-24-jest/jest-doc-5/


上一篇
Unit Test 觀念學習 - 3A Pattern、名詞 (SUT、DOC)
下一篇
透過 spyOn 改寫模擬函式
系列文
<< 測試魔法 >> 這能動嗎?不然就測測看好了!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言